#include <buffer.h>

// 构造函数
Buffer::Buffer(int initBuffSize = 1024) : buffer_(initBuffSize), readPos_(0), writePos_(0) {}

// 返回可写可读以及空闲的字节数
size_t Buffer::WritableBytes() const
{
    return buffer_.size() - writePos_;
}

size_t Buffer::ReadableBtyes() const
{
    return writePos_ - readPos_;
}

size_t Buffer::PrependabelBytes() const
{
    return readPos_;
}

// 返回可读数据的起点地址
const char *Buffer::Peek() const
{
    return &buffer_[readPos_];
}

// 确保有len长度的可写空间
void Buffer::EnsureWritable(size_t len)
{
    if (len > WritableBytes())
    {
        MakeSpace_(len);
    }
    assert(len <= WritableBytes());
}

// 移动写下标
void Buffer::HasWritten(size_t len)
{
    writePos_ += len;
}

// 读取len长度的数据时，移动下标
void Buffer::Retrieve(size_t len)
{
    readPos_ += len;
}
// 读取到end位置
void Buffer::RetrieveUntil(const char *end)
{
    assert(Peek() <= end);
    Retrieve(end - Peek());
}

// 取出所有数据，buffer中数据清零，读写下标归零
void Buffer::RetrieveAll()
{
    bzero(&buffer_[0], buffer_.size());
    readPos_ = 0;
    writePos_ = 0;
}
// 将剩余可读数据读取到str，并清空buffer
std::string Buffer::RetrieveAllToStr()
{
    std::string str(Peek(), ReadableBtyes());
    RetrieveAll();
    return str;
}

// 返回可写位置指针，区分权限
const char *Buffer::BeginWriteConst() const
{
    return &buffer_[writePos_];
}
char *Buffer::BeginWrite()
{
    return &buffer_[writePos_];
}

// 重载，从不同地方添加数据到buffer写缓冲区
void Buffer::Append(const char *str, size_t len)
{
    assert(str);
    EnsureWritable(len);
    std::copy(str, str + len, BeginWrite());
    HasWritten(len);
}

void Buffer::Append(const std::string &str)
{
    Append(str.c_str(), str.size());
}

void Buffer::Append(const void *data, size_t len)
{
    Append(static_cast<const char *>(data), len);
}
void Buffer::Append(const Buffer &buff)
{
    Append(buff.Peek(), buff.ReadableBtyes());
}

// 从fd读数据
ssize_t Buffer::ReadFd(int fd, int *Errno)
{
    char buff[65535];
    struct iovec iov[2];
    size_t writable = WritableBytes();

    iov[0].iov_base = BeginWrite();
    iov[0].iov_len = writable;
    iov[1].iov_base = buff;
    iov[1].iov_len = sizeof(buff);

    ssize_t len = readv(fd, iov, 2);
    if (len < 0)
    {
        *Errno = errno;
    }
    else if (static_cast<size_t>(len) <= writable)
    {
        writePos_ += len;
    }
    else
    {
        writePos_ = buffer_.size();
        Append(buff, static_cast<size_t>(len - writable));
    }
    return len;
}

// 写数据到fd
ssize_t Buffer::WriteFd(int fd, int *Errno)
{
    ssize_t len = write(fd, Peek(), ReadableBtyes());
    if (len < 0)
    {
        *Errno = errno;
        return len;
    }
    Retrieve(len);
    return len;
}
